package runArcon;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileFilter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;


import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;

import backboneCode.GlobalStorage;

public class RunArconCode {

	ArconPath aPath = new ArconPath();
	/**
	 * The constructor
	 */
	public RunArconCode() {
		
	}
	/**
	 * The method that are used to execute ArCon.exe when it's found
	 * @param path The path to ArCon.exe
	 * @return Boolean depending if it was possible to start ArCon.exe  
	 */
	private String[] RunArCon(String path) {		
		try {
			String[] args = GlobalStorage.getArconArguments();
			
			//path = fixString(path);
			for (int i = 0; i < args.length; i++) {
				args[i] = fixString(args[i]);
			}
			
			String cmdLine = path;//"cmd" + " /c" + " start " +v  
			for (int i = 0; i < args.length; i++) {
				cmdLine = cmdLine + " " + args[i];
			}
			
			//Process p = new ProcessBuilder(path, args[0]).start();
		    Process p = Runtime.getRuntime().exec(cmdLine);
		    BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
		    
		    String line = null;
		    String[] temp = new String[100];
		    int j = 0;
		    while ((line = in.readLine()) != null) {
		    	System.out.println(line);
		    	temp[j] = line;
		    	j++;
		    }
			
		    return temp;
		} catch (IOException e) {
			e.printStackTrace(); // Auto-generated catch block
			return null;
		}
	}
	
	public String[] runArCon() {
		
		String[] running = RunArCon(GlobalStorage.getArconPath());
		return running;
	}
	
	/**
	 * This method checks if the path of ArCon is known, otherwise it start a search for it 
	 * @param shell The parent so it would be possible to open a FileDialog
	 * @return Returns the path to ArCon if ArCon is found, otherwise null
	 */
	public String GetArconPath(Shell shell) {
		//boolean for the check if the file with path to ArCon exists 
		boolean exist = false;
		String directory = null;
		File Arcon_cache = new File("ArCon_cache.txt");
		if (Arcon_cache.exists()) {
			exist = true;
			//Getting the path to ArCon from the file 
			directory = aPath.arconPath("get", directory);
			if (!(new File(directory)).exists()) { //A check to see if the file specified exist
				//If it didn't exist, sets the boolean to false and deletes the file
				exist = false;
				Arcon_cache.delete();
			}
		}
		if (!exist) { //If the file doesn't exist (anymore)
			MessageDialog.openInformation(null, "Search for ArCon", "The program is searching for ArCon and it could take a while");
			LookForArcon LookForArcon = new LookForArcon();
			//Starting the search for ArCon.exe
			directory = LookForArcon.Go();
		}
		if (directory != null) { //Check to see if it was found, and if so, save the path to file
			aPath.arconPath("set", directory);
		} else {
			//If ArCon wasn't found, open a FileDialog for the user to select it
			FileDialog fileDialog = new FileDialog(shell);
			String[] ext = {"*.exe"};
			fileDialog.setFilterExtensions(ext);
			fileDialog.setText("File dialog - Choose the ArCon file");
			directory = fileDialog.open();
			if (directory == null) //A check to see so that a file were chosen
				return null;
			aPath.arconPath("set", directory);
		}
		//Start ArCon and depending on how that goes, return different variables
		return directory;		
	}

	/**
	 * 
	 * @param str
	 * @return
	 */
	private String fixString(String str) {
		
		int strLength = str.length();
		int i = 0, j = i;
		String tempString = "";
		
		if (str.indexOf(" ") == -1)
			return str;
		
		if (str.indexOf("\\ssss", i) != -1 || str.indexOf("/ssssss", i) != -1) {
			char lookFor;
			if (str.indexOf("\\", i) != -1) {
				lookFor = '\\';
			} else {
				lookFor = '/';
			}
			while (i < strLength - 1) {
				i = str.indexOf(lookFor, i + 1);
				j = str.indexOf(lookFor, i + 1);
				if (j == -1)
					j = strLength;
				tempString = str.substring(i + 1, j);
				if (tempString.indexOf(" ") != -1 && j != strLength) {
					str = str.substring(0, i + 1) + "\"" + tempString + "\"" + str.substring(j, strLength);
					i = j;
				} else if (tempString.indexOf(" ") != -1) {
					str = str.substring(0, i + 1) + "\"" + tempString + "\"";
					i = j;
				} else {
					i = j - 1;
				}
				strLength = str.length();				
			}
		} else {
			str = "\"" + str + "\"";
		}
		return str;
	}
}

class LookForArcon {
	//Which file to look for
	final String lookFor = "ArCon.exe";
	/**
	 * The constructor
	 */
	public LookForArcon() {
	}
		
	/**
	 * The start method for finding ArCon
	 */
	public String Go() {
		File[] rootDir = File.listRoots();
		String directory = findArCon(rootDir);
		return directory;
	}
	/**
	 * findArCon searches for ArCon.exe in rootDirs, and if it isn't found the method looks for it in a subfolder
	 * @param rootDirs This is the folder in which the method looks for ArCon
	 * @return Returns the path to ArCon if found, otherwise "null"
	 */
	private String findArCon(File[] rootDirs) {
		//Goes through every folder in rootDirs
		for (File dir : rootDirs) {
			//A filter to only get the folders
			FileFilter dirFilter = new FileFilter() {
				public boolean accept(File file) {
					return file.isDirectory();
				}
			};
			//A filter to only get the files
			FileFilter fileFilter = new FileFilter() {
				public boolean accept(File file) {
					return file.isFile();
				}
			}; 
			
			//Get the files in the current folder
			File[] files = dir.listFiles(fileFilter);
			if (files != null) {
				//If there are indeed files in the folder, this goes through them to check if anyone
				//of them is ArCon.exe 
				for (File file : files) {
					//Means to only get the filename without the entire path
					String currentFile = file.toString();
					currentFile = currentFile.substring(currentFile.lastIndexOf("\\")+1);
					if (currentFile.equalsIgnoreCase(lookFor))
						//If ArCon found, return the path for it
						return file.toString();
				}
			}
			
			String result = null;
			//Get the subfolders in the current folder
			File[] dirs = dir.listFiles(dirFilter);
			if (dirs != null)
				//Do recursive search for the file
				//TODO is the above the correct meaning??
				result = findArCon(dirs);
			if (result != null)
				return result;
		}
		return null;
	}
}

class ArconPath {
	/**
	 * The constructor
	 */
	public ArconPath() {
	}
	/**
	 * arconPath either saves or loads data from file
	 * @param gs It determines if directory should be saved to or loaded from a file
	 * @param directory Depending on the gs variable this variable is either saved or loaded
	 * @return Returns either "null", "the path" or "done" depending on gs and how it did go  
	 */
	public String arconPath(String gs, String directory) { //gs is a temporary variable name
		//Two variables used to read from the file
		FileReader rstream;
		BufferedReader in;
		
		//Two variables used to write from the file
		FileWriter wstream;
		BufferedWriter out;
		
		//The file that are written to/read from
		File Arcon_cache = new File("ArCon_cache.txt");
		
		if (gs.equalsIgnoreCase("set")){
			/*
			 * Save the path to ArCon (the directory variable) to a file
			 */
			try {
				wstream = new FileWriter(Arcon_cache.getName());
				out = new BufferedWriter(wstream);
				out.write(directory);
				out.close();
			} catch(IOException e) {
				e.printStackTrace(); // Auto-generated catch block
				return null;
			}
			return "done";
		} else if (gs.equalsIgnoreCase("get")) {
			/*
			 * Load the path to ArCon and set the directory variable to it
			 */
			try {
				rstream = new FileReader(Arcon_cache.getName());
				in = new BufferedReader(rstream);
				directory = in.readLine();
				in.close();
			} catch (Exception e) {
				e.printStackTrace(); // Auto-generated catch block
				return null;
			}
			return directory;
		} else {
			//If not the correct gs variable was used, return "null" 
			return null;
		}
	}
}